/**
 * @file VectorFunctionFactory.h
 * @brief The factory to build vector functions.
 * @author XDDDD
 * @version 
 * @date 2021-04-28
 */

#ifndef __PAISLEYPARK__VECTORFUNCTIONFACTORY_H__
#define __PAISLEYPARK__VECTORFUNCTIONFACTORY_H__

#include "VectorFunction.h"
#include <map>
#include <cstring>

template <std::size_t N, std::size_t M>
class VectorFunctionFactory {
public:
	typedef VectorFunction<N, M>* (*CreateVectorFunctionCallback)();
private:
	typedef std::map<int , CreateVectorFunctionCallback> CallbackMp;
public:
	bool RegisterFunction(const int _FunctionId, CreateVectorFunctionCallback _createFn);
	bool UnregisterFunction(const int _FunctionId);
	VectorFunction<N, M>* CreateFunction(const int _FunctionId);
	~VectorFunctionFactory(){};
	static VectorFunctionFactory<N, M>* Instance() {
		if(!__obj) {
			__obj = new VectorFunctionFactory<N, M>;
		}
		return __obj;
	};
private:
	static VectorFunctionFactory<N, M>* __obj;
	CallbackMp __callbacks;
	VectorFunctionFactory(){};
};


template <std::size_t N, std::size_t M>
VectorFunctionFactory<N, M>* VectorFunctionFactory<N, M>::__obj = 0;

template <std::size_t N, std::size_t M>
bool VectorFunctionFactory<N, M>::RegisterFunction(const int _FunctionId, CreateVectorFunctionCallback _createFn) {
	return __callbacks.insert(typename CallbackMp::value_type(_FunctionId, _createFn)).second;
};

template <std::size_t N, std::size_t M>
bool VectorFunctionFactory<N, M>::UnregisterFunction(const int _FunctionId) {
	return __callbacks.erase(_FunctionId) == 1;
};

template <std::size_t N, std::size_t M>
VectorFunction<N, M>* VectorFunctionFactory<N, M>::CreateFunction(const int _FunctionId) {
	typename CallbackMp::const_iterator i = __callbacks.find(_FunctionId);
	if(i == __callbacks.end()) {
		std::cerr << "Unknown Function Id." << std::endl;
		std::exit(-1);
	}
	return (i->second)();
}

#else
//Do nothing.
#endif
